home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
REXP_SRC
/
GREP.C
next >
Wrap
C/C++ Source or Header
|
1989-09-18
|
8KB
|
354 lines
#define ABOUT "usage: grep([flags],regular expression,input)\rgrep XFCN v3.1 by Greg Anderson 14 Sept 1989"
/*
| | grep XFCN:
| |
| | Greg Anderson
| | 24 Kerr Hall
| | Social Sciences Computing
| | University of California, Santa Cruz
| | sirkm@ssyx
| |
| | Given a search string and the contents of a card/background
| | field, grep returns every line from the input field that
| | contains the search string.
| |
| | Standard regular expressions are supported. See the file 'regexp.c'.
| |
| | Flags:
| |
| | -i : ignore case while searching
| | -n : number each output line w/ its position in the input
| | If the 'n' is followed immediately by a number (e.g. '-n3'),
| | then each line number will be padded to that many
| | characters. Padding is usually done with spaces, although
| | zeros may be specified printf-style (i.e., '-n03').
| | -c : display number of matches instead of output
| | -v : inverted search: lines that DON'T match are returned
| |
| | Non-UNIX flags:
| |
| | -m : multiline match: indented lines are considered to be
| | part of the preceeding line.
| | -f : folded line match: lines that end with a backslash ("\")
| | are considered to be continued on the next line.
| |
| | Example: Extracting a long, folded Cc: line from a mail message:
| |
| | put grep("-fi","^Cc:",theMail) into cc
| |
| | or: Removing all blank lines:
| |
| | put grep("-v","^$",foo) into foo
| |
| |
|*/
#include <MacTypes.h>
#include <FileMgr.h>
#include <SetUpA4.h>
#include "HyperXCmd.h"
#include "XCmdUtil.h"
#include "regexp.h"
/*-----------------------------------------------------------------
| Global variables:
-----------------------------------------------------------------*/
char padchar;
int spaces,
grep_line,
grep_matches;
/*-----------------------------------------------------------------
| Function types
-----------------------------------------------------------------*/
pascal void main();
void grep();
char searchline();
char endsearch();
char copyline();
void copynumber();
char advanceline();
/*-----------------------------------------------------------------
| This is the entry point to grep
-----------------------------------------------------------------*/
pascal void main (paramPtr)
XCmdBlockPtr paramPtr;
{
char *list;
int i;
/*
| | Fix up LSC
*/
RememberA0();
SetUpA4();
/*
| | Check for the propper number of parameters
*/
if( paramPtr->paramCount == 0 )
{
ReturnMsg(paramPtr,ABOUT);
return;
}
if( (paramPtr->paramCount < 2) || (paramPtr->paramCount > 3) )
{
ReturnMsg(paramPtr,"Error in number of parameters.");
return;
}
/*
| | Move all parameters to top of heap and protect them
*/
for (i=0;i<paramPtr->paramCount;i++)
{
MoveHHi(paramPtr->params[i]);
HLock(paramPtr->params[i]);
}
/*
| | Initialize global variables
*/
padchar = ' ';
spaces = 0;
grep_line = 0;
grep_matches = 0;
regexp_flags = 0; /* From regexp.c */
/*
| | Search through flags, if any were specified
*/
list = *(paramPtr->params[0]);
if( (paramPtr->paramCount == 3) )
{
while( *list )
{
switch( *list++ )
{
case 'v': regexp_flags |= INVERT;
break;
case 'i': regexp_flags |= IGNORE;
break;
case 'n': regexp_flags |= NUMBER;
while( (*list >= '0') && (*list <= '9') )
{
if( !spaces && (*list == '0') )
padchar = '0';
spaces = spaces * 10 + (*list - '0');
++list;
}
break;
case 'c': regexp_flags |= COUNT;
break;
case 'm': regexp_flags |= MULTILINE;
break;
case 'f':
case 'M': regexp_flags |= FOLDEDLINE;
break;
}
}
}
/*
| | Do the xcmd
*/
grep(paramPtr);
/*
| | Unprotect the parameters so they can be freed by HyperCard
*/
for (i=0;i<paramPtr->paramCount;i++)
HUnlock(paramPtr->params[i]);
/*
| | The last thing to do before exiting:
*/
RestoreA4();
}
/*-----------------------------------------------------------------
| Search for the specified pattern
-----------------------------------------------------------------*/
void grep(paramPtr)
XCmdBlockPtr paramPtr;
{
Handle tempBuf;
char *searchstring,
*end,
*str,
*in,
*out;
int i,
regexpparam,
textparam,
searchlen;
long handLen;
regexpparam = (paramPtr->paramCount == 3);
textparam = regexpparam + 1;
/*
| |Create a temporary buffer the same size as the text buffer.
*/
handLen = GetHandleSize(paramPtr->params[textparam]) + 100L;
tempBuf = NewHandle((long)handLen);
if( !tempBuf )
{
ReturnMsg(paramPtr,"Error allocating memory.");
return;
}
MoveHHi(tempBuf);
HLock(tempBuf);
searchstring = *(paramPtr->params[regexpparam]);
searchlen = greplen(&searchstring);
in = *(paramPtr->params[textparam]);
out = *tempBuf;
if( searchlen < 0 )
{
DisposHandle(tempBuf);
ReturnMsg(paramPtr,"Error in search string.");
return;
}
while( searchline(searchstring,&in,&out) );
/*
| | If the COUNT flag is set, then overwrite the output
| | with the number of matches
*/
if( regexp_flags & COUNT )
{
out = *tempBuf;
copynumber(grep_matches,&out);
}
*out = 0;
paramPtr->returnValue = tempBuf;
}
/*-----------------------------------------------------------------
| Check if the current line contains the search pattern
-----------------------------------------------------------------*/
char searchline(searchstring,in,out)
char *searchstring,
**in,
**out;
{
char *start,
*end,
**start_p = &start,
**end_p = &end;
int found;
/*
| | If there is nothing on the last line, then it is not a line.
*/
if( **in == 0 ) return(0);
++grep_line;
if( regexp_flags & BEGINFLAG ) start_p = 0;
if( regexp_flags & ENDFLAG ) end_p = 0;
found = find_regexp(searchstring,*in,start_p,end_p);
return( endsearch(in,out,found) );
}
/*-----------------------------------------------------------------
| The search has ended: if match == 1, then the current line has
| a match on it.
-----------------------------------------------------------------*/
char endsearch(in,out,match)
char **in,
**out;
int match;
{
if( regexp_flags & INVERT )
match = !match;
if( match )
{
++grep_matches;
if( regexp_flags & NUMBER )
{
copynumber(grep_line,out);
*(*out-1) = ':';
*(*out)++ = ' ';
}
return( copyline(in,out) );
}
else
return( advanceline(in) );
}
/*-----------------------------------------------------------------
| The pattern was not found on this line; advance pointer
-----------------------------------------------------------------*/
char advanceline(fieldptr)
char **fieldptr;
{
while( !end_of_line(*fieldptr) )
(*fieldptr)++;
return( *(*fieldptr)++ );
}
/*-----------------------------------------------------------------
| If a pattern is found, copy the line to the output buffer
-----------------------------------------------------------------*/
char copyline(fieldptr,outputptr)
char **fieldptr,
**outputptr;
{
while( !end_of_line(*fieldptr) )
{
*(*outputptr)++ = *(*fieldptr)++;
}
*(*outputptr)++ = '\r';
return( *(*fieldptr)++ );
}
/*-----------------------------------------------------------------
| Pad spaces before a number, if necessary.
-----------------------------------------------------------------*/
padspaces(number,n_spaces,out)
char **out;
{
int n = 10,
m = 1;
while( m < n_spaces )
{
if( (number < n) || (m > 4) )
*(*out)++ = padchar;
n *= 10;
++m;
}
}
/*-----------------------------------------------------------------
| Copy a number into the output buffer
-----------------------------------------------------------------*/
void copynumber(n,out)
int n;
char **out;
{
char temp[80],
*ptr;
padspaces(n,spaces,out);
ptr = temp;
itoa(ptr,n);
copyline(&ptr,out);
}
/*-----------------------------------------------------------------
| Count the number of characters on this line
-----------------------------------------------------------------*/
int lineLen(line)
char *line;
{
int len = 0;
while( !end_of_line(line) )
{
++len;
++line;
}
return(len);
}